package com.hup.minicontroller.server.service;

import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;

import com.hup.minicontroller.common.constant.NetConstant.ConnectType;
import com.hup.minicontroller.common.framework.MainThreadHandler;
import com.hup.minicontroller.common.framework.NotCrashExceptionHandler;
import com.hup.minicontroller.common.framework.SubThreadHandler;
import com.hup.minicontroller.server.R;
import com.hup.minicontroller.server.ServerApplication;
import com.hup.minicontroller.server.androidService.AppService;
import com.hup.minicontroller.server.auth.FloaterAuthForCFS;
import com.hup.minicontroller.server.model.AppConfig;
import com.hup.minicontroller.server.model.AppState;
import com.hup.minicontroller.server.mvp.ICursorFloaterView;
import com.hup.minicontroller.server.mvp.IScreenImageService;
import com.hup.minicontroller.server.mvp.IServerHandler;
import com.hup.minicontroller.server.mvp.IServerHandler.ServerHandlerList;
import com.hup.minicontroller.server.receiver.BootReceiver;
import com.hup.minicontroller.server.screenImageService.MediaProjectionScreenService;

import lombok.Getter;


public class MainService {
    private static final String TAG = MainService.class.getSimpleName();
    /**
     * 是否为系统应用
     */
    public static final boolean IS_SYSTEM_APP = false;
    /**
     * <pre>
     * true-在启动app时就一直启动录屏服务(申请权限,没客户端时不处理数据),服务生命周期由 {@link AppService}管理
     * false-只在客户端上下线时切换录屏服务,适合"申请权限界面有下次一定按钮"的设备
     */
    public static final boolean SWITCH_SCREEN_ON_BOOT = true;
    /**
     * 开发模式,打包时修改
     */
    public static final boolean DEV_MODE = true;

    @Getter
    private final AppState appState;
    @Getter
    private static SharedPreferences sp;


    public MainService(Context context) {
        if (DEV_MODE) NotCrashExceptionHandler.registerHandler();
        if (!IS_SYSTEM_APP) Log.w(TAG, "MainService: 当前不是系统app;被影响的功能:触摸功能,光标显示功能");

        sp = context.getSharedPreferences(getClass().getSimpleName(), Context.MODE_PRIVATE);

        appState = new AppState();
        appState.getControlConfig().loadConfig(sp);
        //此处加载或异步加载appState的配置文件
        if (!FloaterAuthForCFS.hasAuth()) appState.getControlConfig().setShowCursor(false);

        initBean(context);
        initDeviceStateListener(context);
        AppService.switchService(true);

        afterAppStarted();
    }

    private void initBean(Context context) {
        ServerApplication.putBean(this);
        SubThreadHandler subThreadHandler = SubThreadHandler.registerSubThreadHandler("SubThreadHandler");
        MainThreadHandler mainThreadHandler = ServerApplication.putBean(new MainThreadHandler());
        ServerApplication.putBean(ICursorFloaterView.class, new CursorFloaterService());
        //网络数据处理器
        DataRequestService dataRequestService = new DataRequestService(context, subThreadHandler, mainThreadHandler);
        //服务端处理器
        ServerHandlerList netServerHandlers = new ServerHandlerList();
        netServerHandlers.add(new LanServerService(appState, dataRequestService));
        if (BluetoothAdapter.getDefaultAdapter() != null)
            netServerHandlers.add(new BluetoothServerService(appState, dataRequestService, BluetoothAdapter.getDefaultAdapter()));
        ServerApplication.putBean(ServerHandlerList.class, netServerHandlers);
        ServerApplication.putBean(new LanBroadcastSenderService());
        //录屏服务
        ServerApplication.putBean(IScreenImageService.class, new MediaProjectionScreenService());
        ServerApplication.putBean(new SoundService());
    }

    private void initDeviceStateListener(Context context) {
        /*
        监听wifi状态:api不兼容,不做
            新api使用 ConnectivityManager.registerDefaultNetworkCallback
            旧api使用注册广播
        监听热点启动状态
        监听蓝牙状态
         */
        Log.i(TAG, "initDeviceStateListener: ");
    }

    private void afterAppStarted() {
        ServerApplication.getBean(SubThreadHandler.class).postDelayed(() -> {
            Log.i(TAG, "afterAppStarted: ");
            //开机监听事件在Application.onCreate执行完后才会收到,所以需要postDelay
            if (BootReceiver.getBootTime() != null) {
                Log.i(TAG, "正在开机: ");
            } else {
                Log.i(TAG, "启动成功: ");
            }
            /*
            app启动后自动启动server
            MainActivity也是在Application.onCreate执行完后才会onCreate
             */
            ServerHandlerList netServerHandlers = ServerApplication.getBean(ServerHandlerList.class);
            AppConfig appConfig = appState.getAppConfig();
            if (appConfig.isAutoStartServer()) {
                for (IServerHandler handler : netServerHandlers) {
                    if (ConnectType.LAN.equals(handler.getConnectType()) && appConfig.isAutoStartLan()) {
                        handler.switchServer(true);
                    } else if (ConnectType.BLUETOOTH.equals(handler.getConnectType()) && appConfig.isAutoStartBluetooth()) {
                        handler.switchServer(true);
                    }
                }
            }
        }, 50);
    }

    /**
     * 设备关机时回调
     */
    public void onDeviceShuttingDown() {
        doTerminate(false);
    }

    /**
     * @param fromUser true-用户触发退出程序;false-关机监听触发退出
     */
    public void doTerminate(boolean fromUser) {
        Log.i(TAG, "doTerminate: " + fromUser);
        /*
        exit前必须关闭安卓服务
        无论是app正常System.exit(0)退出,还是主线程有异常后强退,
        只要启动了安卓服务,系统就会自动重启app!
        导致bug强退后日志丢失
         */
        ServerApplication.getBean(ICursorFloaterView.class).doTerminate();
        AppService.switchService(false);
        SubThreadHandler subThreadHandler = ServerApplication.getBean(SubThreadHandler.class);
        subThreadHandler.post(
                () -> ServerApplication.executeForeach(ServerHandlerList.class, IServerHandler::doTerminate));
        ServerApplication.executeIfExist(LanBroadcastSenderService.class, LanBroadcastSenderService::doTerminate);
        ServerApplication.executeIfExist(SoundService.class, s -> s.play(R.raw.shutdown));
        subThreadHandler.postDelayed(() -> {
            ServerApplication.executeIfExist(SoundService.class, SoundService::doTerminate);
            Log.i(TAG, "doTerminate: 马上会执行exit");
            /*
             不需要SubThreadHandler.doTerminate:
             .如果doTerminate,则按了退出后,又马上打开app时,会导致整个app卡死(app启动时会使用SubThreadHandler)
             .不doTerminate的话,退出后马上打开时,app只会一闪后退出,没有异常,不会卡住
             */
            //ServerApplication.getBean(SubThreadHandler.class).doTerminate(false);
            System.exit(0);
        }, 1000);
    }

}
